// 设计相关服务(表二建筑安装工程费计算)
package services

import (
	"bsm/config"
	"bsm/logger"
	"fmt"
	"math"

	"github.com/Knetic/govaluate"
)

// 已知输入数据
type InputDataTab2 struct {
	MechanicDays     float64 // 技工工日
	GeneralDays      float64 // 普工工日
	MainMaterialCost float64 // 主要材料费
	MachineCost      float64 // 机械台班费
	InstrumentCost   float64 // 仪器仪表费
}
type CostItem struct {
	ID          string
	Name        string
	Level       int
	Value       float64
	Calculation string
	DependsOn   []string // 依赖的子节点ID
	ParentID    string   // 新增：父节点ID
	Children    []*CostItem
	Calculated  bool // 新增：标记是否已计算
}

// 计算引擎
type Calculator struct {
	items   map[string]*CostItem
	input   InputDataTab2
	order   []string // 记录计算顺序，用于调试
	vatRate float64  // 增值税率
}

func (c *Calculator) addItem(item *CostItem) {
	c.items[item.ID] = item
}

// ## 初始化费用树结构
// func NewTab2Calculator(input InputDataTab2, vatrate float64) *Calculator {
func (s *designServiceImpl) NewTab2(input InputDataTab2) *Calculator {
	vatRate := config.Get().DesignConfig.VatRate

	c := &Calculator{
		items:   make(map[string]*CostItem),
		input:   input,
		vatRate: vatRate, // 增值税率
	}

	// 构建完整的费用树结构
	c.buildCostTree()
	return c
}

func (c *Calculator) buildCostTree() {
	// 1. 人工费相关
	mechanicLabor := &CostItem{
		ID:          "mechanic_labor",
		Name:        "技工费",
		Level:       4,
		Calculation: "MechanicDays * 114",
		ParentID:    "labor_cost",
	}

	generalLabor := &CostItem{
		ID:          "general_labor",
		Name:        "普工费",
		Level:       4,
		Calculation: "GeneralDays * 61",
		ParentID:    "labor_cost",
	}

	laborCost := &CostItem{
		ID:          "labor_cost",
		Name:        "人工费",
		Level:       3,
		Calculation: "mechanic_labor + general_labor",
		DependsOn:   []string{"mechanic_labor", "general_labor"},
		ParentID:    "direct_engineering",
		Children:    []*CostItem{mechanicLabor, generalLabor},
	}

	// 2. 材料费相关
	mainMaterial := &CostItem{
		ID:          "main_material",
		Name:        "主要材料费",
		Level:       3,
		Calculation: "MainMaterialCost", // 直接引用输入字段
		DependsOn:   []string{},         // 无依赖项
		ParentID:    "material_cost",
	}

	auxMaterial := &CostItem{
		ID:          "aux_material",
		Name:        "辅助材料费",
		Level:       3,
		Calculation: "main_material * 0.003", // 主要材料费的3%
		DependsOn:   []string{"main_material"},
		ParentID:    "material_cost",
	}

	materialCost := &CostItem{
		ID:          "material_cost",
		Name:        "材料费",
		Level:       2,
		Calculation: "main_material + aux_material",
		DependsOn:   []string{"main_material", "aux_material"},
		ParentID:    "direct_engineering",
		Children:    []*CostItem{mainMaterial, auxMaterial},
	}

	// 3. 机械和仪表使用费
	machineCost := &CostItem{
		ID:          "machine_cost",
		Name:        "机械使用费",
		Level:       3,
		Calculation: "MachineCost", // 绑定输入值
		DependsOn:   []string{},
		ParentID:    "direct_engineering",
	}

	instrumentCost := &CostItem{
		ID:          "instrument_cost",
		Name:        "仪表使用费",
		Level:       3,
		Calculation: "InstrumentCost", // 绑定输入值
		DependsOn:   []string{},
		ParentID:    "direct_engineering",
	}

	// 4. 直接工程费
	directEngineering := &CostItem{
		ID:          "direct_engineering",
		Name:        "直接工程费",
		Level:       2,
		Calculation: "labor_cost + material_cost + machine_cost + instrument_cost",
		DependsOn:   []string{"labor_cost", "material_cost", "machine_cost", "instrument_cost"},
		ParentID:    "direct_cost",
		Children:    []*CostItem{laborCost, materialCost, machineCost, instrumentCost},
	}

	// 5. 措施费(包含15个子项)
	safetyConstruction := &CostItem{
		ID:          "safety_construction",
		Name:        "文明施工费",
		Level:       3,
		Calculation: "labor_cost * 0.015",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	equipmentMoving := &CostItem{
		ID:          "equipment_moving",
		Name:        "工地器材搬运费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", //"labor_cost * 0.034",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	interferenceFee := &CostItem{
		ID:          "interference_fee",
		Name:        "工程干扰费",
		Level:       3,
		Calculation: "labor_cost * 0.06",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	siteClearing := &CostItem{
		ID:          "site_clearing",
		Name:        "工程点交、场地清理费",
		Level:       3,
		Calculation: "labor_cost * 0.033",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	temporaryFacilities := &CostItem{
		ID:          "temporary_facilities",
		Name:        "临时设施费",
		Level:       3,
		Calculation: "labor_cost * 0.026", // 默认按≤35千米2.6%
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	engineeringVehicle := &CostItem{
		ID:          "engineering_vehicle",
		Name:        "工程车辆使用费",
		Level:       3,
		Calculation: "labor_cost * 0.05", //
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	nightConstruction := &CostItem{
		ID:          "night_construction",
		Name:        "夜间施工增加费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", //"labor_cost * 0.025",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	winterRain := &CostItem{
		ID:          "winter_rain",
		Name:        "冬雨季施工增加费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", //"labor_cost * 0.018",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	productionTool := &CostItem{
		ID:          "production_tool",
		Name:        "生产工具使用费",
		Level:       3,
		Calculation: "labor_cost * 0.015", //
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	waterElectricity := &CostItem{
		ID:          "water_electricity",
		Name:        "施工用水电蒸汽费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", // 按实计列，默认0
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	specialArea := &CostItem{
		ID:          "special_area",
		Name:        "特殊地区施工增加费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", // 按实计列，默认0
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	protectionFee := &CostItem{
		ID:          "protection_fee",
		Name:        "已完工程及设备保护费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", //"labor_cost * 0.02",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	soilTransportation := &CostItem{
		ID:          "soil_transportation",
		Name:        "运土费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", // 按实计列，默认0
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	teamDispatch := &CostItem{
		ID:          "team_dispatch",
		Name:        "施工队伍调遣费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", // 按实计列，默认0
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	machineryDispatch := &CostItem{
		ID:          "machinery_dispatch",
		Name:        "大型施工机械调遣费",
		Level:       3,
		Value:       0,   // 默认为0
		Calculation: "0", // 按实计列，默认0
		DependsOn:   []string{"labor_cost"},
		ParentID:    "measure_cost",
	}

	// 措施费合计
	measureCost := &CostItem{
		ID:          "measure_cost",
		Name:        "措施费",
		Level:       2,
		Calculation: "safety_construction + equipment_moving + interference_fee + site_clearing + temporary_facilities + engineering_vehicle + night_construction + winter_rain + production_tool + water_electricity + special_area + protection_fee + soil_transportation + team_dispatch + machinery_dispatch",
		DependsOn:   []string{"safety_construction", "equipment_moving", "interference_fee", "site_clearing", "temporary_facilities", "engineering_vehicle", "night_construction", "winter_rain", "production_tool", "water_electricity", "special_area", "protection_fee", "soil_transportation", "team_dispatch", "machinery_dispatch"},
		ParentID:    "direct_cost",
		Children:    []*CostItem{safetyConstruction, equipmentMoving, interferenceFee, siteClearing, temporaryFacilities, engineeringVehicle, nightConstruction, winterRain, productionTool, waterElectricity, specialArea, protectionFee, soilTransportation, teamDispatch, machineryDispatch},
	}

	// 6. 直接费
	directCost := &CostItem{
		ID:          "direct_cost",
		Name:        "直接费",
		Level:       1,
		Calculation: "direct_engineering + measure_cost",
		DependsOn:   []string{"direct_engineering", "measure_cost"},
		Children:    []*CostItem{directEngineering, measureCost},
	}

	// 7. 规费
	pollutionDischarge := &CostItem{
		ID:          "pollution_discharge",
		Name:        "工程排污费",
		Level:       3,
		Value:       0,  // 默认为0
		Calculation: "", // 按规定
		DependsOn:   []string{"labor_cost"},
		ParentID:    "fee",
	}

	socialSecurity := &CostItem{
		ID:          "social_security",
		Name:        "社会保障费",
		Level:       3,
		Calculation: "labor_cost * 0.285",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "fee",
	}

	housingFund := &CostItem{
		ID:          "housing_fund",
		Name:        "住房公积金",
		Level:       3,
		Calculation: "labor_cost * 0.0419",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "fee",
	}

	accidentInsurance := &CostItem{
		ID:          "accident_insurance",
		Name:        "危险作业意外伤害保险费",
		Level:       3,
		Calculation: "labor_cost * 0.01",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "fee",
	}

	fee := &CostItem{
		ID:          "fee",
		Name:        "规费",
		Level:       2,
		Calculation: "pollution_discharge + social_security + housing_fund + accident_insurance", // 工程排污费暂不计
		DependsOn:   []string{"pollution_discharge", "social_security", "housing_fund", "accident_insurance"},
		ParentID:    "indirect_cost",
		Children:    []*CostItem{pollutionDischarge, socialSecurity, housingFund, accidentInsurance},
	}

	// 8. 企业管理费
	managementFee := &CostItem{
		ID:          "management_fee",
		Name:        "企业管理费",
		Level:       2,
		Calculation: "labor_cost * 0.274",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "indirect_cost",
	}

	// 9. 间接费
	indirectCost := &CostItem{
		ID:          "indirect_cost",
		Name:        "间接费",
		Level:       1,
		Calculation: "fee + management_fee",
		DependsOn:   []string{"fee", "management_fee"},
		Children:    []*CostItem{fee, managementFee},
	}

	// 10. 利润
	profit := &CostItem{
		ID:          "profit",
		Name:        "利润",
		Level:       1,
		Calculation: "labor_cost * 0.2",
		DependsOn:   []string{"labor_cost"},
		ParentID:    "",
		Children:    nil,
	}

	// 销项税额节点
	tax := &CostItem{
		ID:          "tax",
		Name:        "销项税额",
		Level:       1,
		Calculation: "(labor_cost + aux_material + machine_cost + instrument_cost + measure_cost + fee + management_fee + profit) * 0.09",
		DependsOn:   []string{"labor_cost", "aux_material", "machine_cost", "instrument_cost", "measure_cost", "fee", "management_fee", "profit"},
		ParentID:    "inclusive_tax_cost", // 父节点是含税总费用
		Children:    nil,
	}

	// 不含税总费用节点
	exclusiveTaxCost := &CostItem{
		ID:          "exclusive_tax_cost",
		Name:        "建筑安装工程费(除税价)",
		Level:       0, // 顶级节点
		Calculation: "direct_cost + indirect_cost + profit",
		DependsOn:   []string{"direct_cost", "indirect_cost", "profit"},
		ParentID:    "", // 没有父节点
		Children:    nil,
	}

	// 含税总费用节点
	inclusiveTaxCost := &CostItem{
		ID:          "inclusive_tax_cost",
		Name:        "建筑安装工程费(含税价)",
		Level:       0, // 顶级节点
		Calculation: "exclusive_tax_cost + tax",
		DependsOn:   []string{"exclusive_tax_cost", "tax"},
		ParentID:    "", // 没有父节点
		Children:    nil,
	}

	// 添加所有节点到映射表
	c.addItem(mechanicLabor)
	c.addItem(generalLabor)
	c.addItem(laborCost)
	c.addItem(mainMaterial)
	c.addItem(auxMaterial)
	c.addItem(materialCost)
	c.addItem(machineCost)
	c.addItem(instrumentCost)
	c.addItem(directEngineering)
	c.addItem(safetyConstruction)
	c.addItem(equipmentMoving)
	c.addItem(interferenceFee)
	c.addItem(siteClearing)
	c.addItem(temporaryFacilities)
	c.addItem(engineeringVehicle)
	c.addItem(nightConstruction)
	c.addItem(winterRain)
	c.addItem(productionTool)
	c.addItem(waterElectricity)
	c.addItem(specialArea)
	c.addItem(protectionFee)
	c.addItem(soilTransportation)
	c.addItem(teamDispatch)
	c.addItem(machineryDispatch)
	c.addItem(measureCost)
	c.addItem(directCost)
	c.addItem(pollutionDischarge)
	c.addItem(socialSecurity)
	c.addItem(housingFund)
	c.addItem(accidentInsurance)
	c.addItem(fee)
	c.addItem(managementFee)
	c.addItem(indirectCost)
	c.addItem(profit)
	c.addItem(tax)
	c.addItem(exclusiveTaxCost)
	c.addItem(inclusiveTaxCost)

}

func (c *Calculator) calculateItem(itemID string) error {
	item, exists := c.items[itemID]
	if !exists {
		logger.WithFields(map[string]interface{}{
			"layer":     "service",
			"operation": "SvcCalculateTab2",
			"item_id":   itemID,
		}).Error("计算表二失败：条目未找到")
		return fmt.Errorf("item %s not found", itemID)
	}

	// 如果已经计算过，直接返回
	if item.Calculated {
		return nil
	}

	// 计算所有依赖项
	for _, depID := range item.DependsOn {
		if err := c.calculateItem(depID); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "service",
				"operation": "SvcCalculateTab2",
				"item_id":   itemID,
				"dep_id":    depID,
			}).Error("计算表二失败：依赖项计算失败")
			return err
		}
	}

	// 执行计算
	value, err := c.evaluateExpression(item.Calculation)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "service",
			"operation": "SvcCalculateTab2",
			"item_id":   itemID,
		}).Error("计算表二失败：表达式计算失败")
		return fmt.Errorf("error calculating %s: %v", itemID, err)
	}

	item.Value = math.Round(value*100) / 100 // 与Excel一致四舍五入
	item.Calculated = true
	c.order = append(c.order, itemID) // 记录计算顺序

	// 如果有父节点，标记父节点需要重新计算
	if item.ParentID != "" {
		c.items[item.ParentID].Calculated = false
	}

	return nil
}

// 从叶子节点开始计算的入口方法
// func (c *Calculator) CalculateTab2() error {
func (c *Calculator) CalculateTab2() error {
	// 重置计算状态
	for _, item := range c.items {
		item.Calculated = false
	}
	c.order = nil

	// 找出所有叶子节点（没有子节点的节点）
	var leafNodes []*CostItem
	for _, item := range c.items {
		if len(item.Children) == 0 {
			leafNodes = append(leafNodes, item)
		}
	}

	// 从叶子节点开始计算
	for _, node := range leafNodes {
		if err := c.calculateItem(node.ID); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "service",
				"operation": "CalculateTab2",
				"item_id":   node.ID,
			}).Error("计算表二失败：叶子节点计算失败")
			return err
		}
	}

	return nil
}

// 使用 govaluate 计算表达式
func (c *Calculator) evaluateExpression(expr string) (float64, error) {
	// 处理空表达式
	if expr == "" {
		return 0, nil
	}

	// 准备参数
	parameters := make(map[string]interface{})

	// 添加输入参数
	parameters["MechanicDays"] = c.input.MechanicDays
	parameters["GeneralDays"] = c.input.GeneralDays
	parameters["MainMaterialCost"] = c.input.MainMaterialCost
	parameters["MachineCost"] = c.input.MachineCost
	parameters["InstrumentCost"] = c.input.InstrumentCost

	// 添加已计算的费用项
	for id, item := range c.items {
		parameters[id] = item.Value
	}

	// 创建表达式
	expression, err := govaluate.NewEvaluableExpression(expr)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "service",
			"operation": "SvcCalculateTab2",
			"expr":      expr,
		}).Error("计算表二失败：表达式解析失败")
		return 0, fmt.Errorf("failed to parse expression '%s': %v", expr, err)
	}

	// 计算表达式
	result, err := expression.Evaluate(parameters)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "service",
			"operation": "SvcCalculateTab2",
			"expr":      expr,
		}).Error("计算表二失败：表达式计算失败")
		return 0, fmt.Errorf("failed to evaluate expression '%s': %v", expr, err)
	}

	// 转换为float64
	switch v := result.(type) {
	case float64:
		return v, nil
	case int:
		return float64(v), nil
	case int64:
		return float64(v), nil
	case float32:
		return float64(v), nil
	default:
		return 0, fmt.Errorf("unexpected result type: %T", result)
	}

}

// 辅助函数
// 添加打印结构体内容的函数
func (c *CostItem) PrintTab2Tree(indent string) {
	fmt.Printf("%s%s (ID: %s, Value: %.2f)\n", indent, c.Name, c.ID, c.Value)
	for _, child := range c.Children { // 这里使用了Children字段
		child.PrintTab2Tree(indent + "  ")
	}
}
